package com.sarc.games;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.opengl.GLUtils;

public class ResourceTexturedQuad 
{
	Context context = null;
	int resourceId = -1;
	int textureId = -1;
	float widthHeightRatio;
	float topLeftX, topLeftY, width, height;
	float[] color = {1f, 1f, 1f, 1f};
	
	
	private static final float
		_X = 1f,
		_Y = 1f,
		_Z = -10f,
		_SX = 1f,
		_SY = 1f;
		
	private static float vertices[] = 
		{
			0f, 1f, 0f,
			0f, 0f, 0f,
			1f, 0f, 0f,
			0f, 1f, 0f,
			1f, 0f, 0f,
			1f, 1f, 0f
		};
	
	private static float textures[] = 
		{
			0f, 1f,
			0f, 0f,
			1f, 0f,
			0f, 1f,
			1f, 0f,
			1f, 1f
		};
		
	private static FloatBuffer vertexBuffer = null;
	private static FloatBuffer textureBuffer = null;
	
	public ResourceTexturedQuad(Context context, int resourceId, float screenWidthHeightRatio, float topLeftX, float topLeftY, float width, float height)
	{
		this(context,resourceId, screenWidthHeightRatio);
		setDimensions(topLeftX, topLeftY, width, height);
	}
	
	public ResourceTexturedQuad(Context context, int resourceId, float screenWidthHeightRatio)
	{
		this(screenWidthHeightRatio);
		loadTextureFromResource(context, resourceId);
	}
	
	public ResourceTexturedQuad(float screenWidthHeightRatio)
	{
		if (vertexBuffer == null)
		{
			ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
			vbb.order(ByteOrder.nativeOrder());
			vertexBuffer = vbb.asFloatBuffer();
			vertexBuffer.put(vertices);
			vertexBuffer.position(0);
			
			ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length * 4);
			tbb.order(ByteOrder.nativeOrder());
			textureBuffer = tbb.asFloatBuffer();
			textureBuffer.put(textures);
			textureBuffer.position(0);
		}
		
		topLeftX = topLeftY = 0f;
		width = height = 1f;
		widthHeightRatio = screenWidthHeightRatio;
	}
	
	public void setColor(float[] color)
	{
		this.color = color;
	}
	
	public void setDimensions(float x, float y, float width, float height)
	{
		this.topLeftX = x;
		this.topLeftY = y;
		this.width = width;
		this.height = height;
	}
		
	public void loadTextureFromResource(Context context, int resourceId)
	{
		this.context = context;
		this.resourceId = resourceId;
	}
	
	public void preload(GL10 gl)
	{
		textureId = loadTexture(gl, context, resourceId);
	}
	
	public void render(GL10 gl)
	{
		//if texture not loaded, load it.
		if (textureId == -1 && resourceId != -1)
		{
			preload(gl);
		}
		
		//set up
		gl.glPushMatrix();
		
		gl.glTranslatef(_X, _Y, _Z);
		gl.glScalef(_SX, _SY, 1f)
		
		gl.glTranslatef(topLeftX, topLeftY, 0);
		gl.glScalef(width, height, 1f);
		
		gl.glEnable(GL10.GL_BLEND);
		gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
		
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
				
		
		//draw the inner square
		gl.glColor4f(color[0],color[1],color[2],color[3]);
		gl.glDrawArrays(GL10.GL_TRIANGLES, 0, vertices.length / 3);
		
		//reset color
		gl.glColor4f(1, 1, 1, 1);
		
		//clean up
		gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glDisable(GL10.GL_CULL_FACE);
		gl.glDisable(GL10.GL_TEXTURE_2D);
		gl.glDisable(GL10.GL_BLEND);
		gl.glPopMatrix();
	}
		
	private int loadTexture(GL10 gl, Context context, int resource) {
	    
	    // In which ID will we be storing this texture?
	    int[] tempInt = new int[1];
	    gl.glGenTextures(1, tempInt, 0);
	    int id = tempInt[0];
	    
	    // We need to flip the textures vertically:
	    Matrix flip = new Matrix();
	    flip.postScale(1f, -1f);
	    
	    // This will tell the BitmapFactory to not scale based on the device's pixel density:
	    // (Thanks to Matthew Marshall for this bit)
	    BitmapFactory.Options opts = new BitmapFactory.Options();
	    opts.inScaled = false;
	    
	    // Load up, and flip the texture:
	    Bitmap temp = BitmapFactory.decodeResource(context.getResources(), resource, opts);
	    Bitmap bmp = Bitmap.createBitmap(temp, 0, 0, temp.getWidth(), temp.getHeight(), flip, true);
	    temp.recycle();
	    
	    gl.glBindTexture(GL10.GL_TEXTURE_2D, id);
	    
	    // Set all of our texture parameters:
	    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR_MIPMAP_NEAREST);
	    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR_MIPMAP_NEAREST);
	    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
	    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
	    
	    gl.glEnable(GL10.GL_BLEND);
	    gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
	    // Generate, and load up all of the mipmaps:
	    for(int level=0, height = bmp.getHeight(), width = bmp.getWidth(); true; level++) {
	        // Push the bitmap onto the GPU:
	        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, level, bmp, 0);
	        
	        // We need to stop when the texture is 1x1:
	        if(height==1 && width==1) break;
	        
	        // Resize, and let's go again:
	        width >>= 1; height >>= 1;
	        if(width<1)  width = 1;
	        if(height<1) height = 1;
	        
	        Bitmap bmp2 = Bitmap.createScaledBitmap(bmp, width, height, true);
	        bmp.recycle();
	        bmp = bmp2;
	    }
	    	
	    gl.glDisable(GL10.GL_BLEND);
	    bmp.recycle();
	    
	    return id;
	}
	
	public boolean hitTest(float x, float y)
	{
		boolean hit = false;
		if (x > topLeftX && y > topLeftY)
		{
			if (x < topLeftX + width && y < topLeftY + height)
			{
				hit = true;
			}
		}
		return hit;
	}
}
